<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
	</head>
	<body>
		<input type="text" id="inp">
		<p class="div"></p>
		<script>
			let divS = document.querySelector(".div")
			let divNum = 1
			function Move() {
				divS.innerHTML = divNum++
			}
			document.addEventListener("mouseover", debounce(Move, 1000))
			// 1.封装防抖函数 **防抖重在清零 clearTimeout(timer)**
			function debounce(fn, delay, immediate = false) {
				// 4.创建一个标记用来存放定时器的返回值
				let timer = null;
				return function() {
					if (immediate) {
						fn();
						immediate = false;
						return;
						let callNow = !timer;
						console.log("timer1", timer, !timer, callNow)
						// console.log("timer", timer)
						clearTimeout(timer);
						timer = setTimeout(() => {
							// console.log("timerSetT", timer, !timer)
							timer = null
							// console.log("timerSetT2", timer, !timer)
						}, delay);
						console.log("timer2", timer, !timer, callNow)
						if (callNow) {
							fn();
						}
					} else {
						// 5.每当用户触发input事件  把前一个 setTimeout 清楚掉
						clearTimeout(timer);
						// 6.然后又创建一个新的 setTimeout, 这样就能保证输入字符后等待的间隔内 还有字符输入的话，就不会执行 setTimeout里面的内容
						timer = setTimeout(() => {
							// 7.这里进行防抖的内容
							fn();
						}, delay);
					}
				};
			}

			// 2.获取inpt元素
			var inp = document.getElementById('inp');
			// 8. 测试防抖临时使用的函数
			function sayHi() {
				console.log('防抖成功');
			}
			// 3.给inp绑定input事件  调用封装的防抖函数  传入要执行的内容与间隔事件 
			inp.addEventListener('input', debounce(sayHi, 2000, true));

			/*
			var obj = {
				name: "ab"
			}
			var timer

			function sumT() {
				if (timer) clearTimeout(timer)
				timer = setTimeout(function() {
					console.log(timer, 'setTimeout')
					// fn.apply(_this, args)
				}.bind(obj), 2000);
			};

			// window.onresize = sumT


			function sum(a, b) {
				console.log(a + b); // 输出 30
			}
			setTimeout(sum, 1000, 10, 20);
			// setTimeout(sum(10, 20), 1000);

			// 防抖函数
			function debounce(fn, wait) {
				let timer;
				console.log(timer, 'timer')
				return function() {
					let _this = this;
					let args = arguments;
					// console.log(_this, 'this2')
					console.log(timer, 'timer2')
					if (timer) clearTimeout(timer)
					timer = setTimeout(function() {
						console.log(this, 'setTimeout')
						fn.apply(_this, args)
					}, wait);
					console.log(timer, 'timer3')
				}
			}
			// 使用
			window.onresize = debounce(function fn() {
				console.log(1)
			}, 2000)
			*/

			// 节流
			// 方式1: 使用时间戳
			function throttle1(fn, wait) {
				let time = 0;
				return function() {
					let _this = this;
					let args = arguments;
					let now = Date.now()
					console.log(now - time, "now - time")
					if (now - time > wait) {
						fn.apply(_this, args);
						time = now;
						console.log(now - time, "now - time2")
					}
				}
			}

			// 方式2: 使用定时器
			function throttle2(fn, wait) {
				let timer;
				return function() {
					let _this = this;
					let args = arguments;
					console.log(timer, "timer")
					// debugger
					if (!timer) {
						// clearTimeout(timer);
						timer = setTimeout(function() {
							timer = null;
							console.log(null, "null")
							fn.apply(_this, args)
						}, wait)
						console.log(timer, "timer2")
					}
				}
			}

			// 1.封装节流函数（使用定时器） 节流重在加锁 timer=timeout
			function throttle(fn, time) {
				//3. 通过闭包保存一个 "节流阀" 默认为false
				let temp = false;
				return function() {
					// debugger
					console.log(temp, "temp")
					//8.触发事件被调用 判断"节流阀" 是否为true  如果为true就直接trurn出去不做任何操作
					if (temp) {
						return;
					} else {
						//4. 如果节流阀为false  立即将节流阀设置为true
						temp = true; //节流阀设置为true
						//5.  开启定时器
						setTimeout(() => {
							//6. 将外部传入的函数的执行放在setTimeout中
							fn.apply(this, arguments);
							// console.log(arguments, "arguments")
							//7. 最后在setTimeout执行完毕后再把标记'节流阀'为false(关键)  表示可以执行下一次循环了。当定时器没有执行的时候标记永远是true，在开头被return掉
							temp = false;
						}, time);
					}
					console.log(temp, "temp2")
				};
			}

			function sayThrottle(e) {
				// 打印当前 document 的宽高
				console.log(e.target.innerWidth, e.target.innerHeight);
			}
			// 2.绑定事件，绑定时就调用节流函数  
			// 敲黑板！！！ 这里是重点 绑定是就要调用一下封装的节流函数 触发事件是触发封装函数内部的函数
			// window.addEventListener('resize', throttle(sayThrottle, 2000));
			// window.addEventListener('resize', throttle1(sayThrottle, 2000));
		</script>
	</body>
</html>